package com.atguigu.srb.core.service.impl;

import com.alibaba.fastjson.JSON;
import com.atguigu.srb.core.hfb.FormHelper;
import com.atguigu.srb.core.hfb.HfbConst;
import com.atguigu.srb.core.hfb.RequestHelper;
import com.atguigu.srb.core.mapper.UserAccountMapper;
import com.atguigu.srb.core.pojo.entity.TransFlow;
import com.atguigu.srb.core.pojo.entity.UserAccount;
import com.atguigu.srb.core.pojo.entity.UserInfo;
import com.atguigu.srb.core.service.TransFlowService;
import com.atguigu.srb.core.service.UserAccountService;
import com.atguigu.srb.core.service.UserInfoService;
import com.atguigu.srb.result.ResponseEnum;
import com.atguigu.srb.util.SrbAssert;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * 用户账户 服务实现类
 * </p>
 *
 * @author Atguigu
 * @since 2024-04-15
 */
@Service
@Slf4j
public class UserAccountServiceImpl extends ServiceImpl<UserAccountMapper, UserAccount> implements UserAccountService {
    @Resource
    private UserInfoService userInfoService;
    @Resource
    private TransFlowService transFlowService;
    @Override
    public String recharge(String token, BigDecimal chargeAmt) {
        HashMap<String, Object> params = new HashMap<>();
        params.put("agentId", HfbConst.AGENT_ID);
        String agentBillNo = IdWorker.getIdStr();
        params.put("agentBillNo",agentBillNo );
        UserInfo userInfo = userInfoService.checkUserBaseInfo(token);
        params.put("bindCode",userInfo.getBindCode());
        params.put("chargeAmt",chargeAmt);
        params.put("feeAmt",0);
        // http://192.168.1.110/api/core/userAccount/notify
        params.put("notifyUrl",HfbConst.RECHARGE_NOTIFY_URL);
        params.put("returnUrl",HfbConst.RECHARGE_RETURN_URL);
        params.put("timestamp",System.currentTimeMillis());
        params.put("sign", RequestHelper.getSign(params));
        // 向trans_flow中添加一条记录，保证`幂等性的校验`和`充值金额的校验`
        TransFlow transFlow = new TransFlow();
//        transFlow.setMemo();
        transFlow.setTransAmount(chargeAmt);
        transFlow.setTransNo(agentBillNo);
        transFlow.setTransType(1);
        transFlow.setTransTypeName("充值");
        transFlow.setUserId(userInfo.getId());
        transFlow.setUserName(userInfo.getName());
//        transFlow.setIsUsed();
        transFlowService.save(transFlow);
        String form = FormHelper.buildForm(HfbConst.RECHARGE_URL, params);
        return form;
    }

    @Override
    public String rechargeNotify(Map<String, Object> map) {
        String resultCode = map.get("resultCode").toString();
        String bindCode = map.get("bindCode").toString();
        String agentBillNo = map.get("agentBillNo").toString();
        BigDecimal rechargeAmtReal = new BigDecimal(map.get("chargeAmt").toString());
        // 0. 幂等性的校验： 去tans_flow表中根据`订单编号`获取transFlow对象，校验是否使用过
        TransFlow transFlow = transFlowService.getOne(Wrappers.lambdaQuery(TransFlow.class).eq(TransFlow::getTransNo, agentBillNo));
        if(transFlow==null){
            log.warn("充值失败，接口的恶意访问，已拒绝");
            return "fail";
        }
        transFlow.setMemo(JSON.toJSONString(map));
        if(transFlow.getIsUsed()==1){
            log.warn("充值失败，接口的恶意访问，已拒绝");
            return "fail";
        }
        transFlowService.update(Wrappers.lambdaUpdate(TransFlow.class)
                .set(TransFlow::getIsUsed,1).eq(TransFlow::getTransNo,agentBillNo));
        // 0.1.  判断hfb处理用户充值的结果
        UserInfo userInfo = userInfoService.getOne(Wrappers.lambdaQuery(UserInfo.class).eq(UserInfo::getBindCode, bindCode));
        if(!"0001".equals(resultCode)){
            log.warn("充值失败,{}",map.toString());
            return "fail";
        }
        // 1. 验证签名，保证数据的安全性
        if(!RequestHelper.isSignEquals(map)){
            log.warn("充值失败,{}","数据被篡改");
            return "fail";
        }
        // 2. 校验用户实际充值金额和用户提交的充值金额，如果相同则成功，否则充值失败
        BigDecimal transAmount = transFlow.getTransAmount();
        if(!(transAmount.compareTo(rechargeAmtReal)==0)){
            log.warn("充值失败，充值的金额与实际不符");
            return "fail";
        }
        // 3. 更新我们项目中的用户账户
        UserAccount userAccount = this.getOne(Wrappers.lambdaQuery(UserAccount.class).eq(UserAccount::getUserId, userInfo.getId()));
        userAccount.setAmount(userAccount.getAmount().add(rechargeAmtReal));
        this.updateById(userAccount);
        return "success";
    }

    @Override
    public BigDecimal getBalance(Long userId) {
        UserAccount userAccount = this.getOne(Wrappers.lambdaQuery(UserAccount.class).eq(UserAccount::getUserId, userId));
        SrbAssert.assertNotNull(userAccount, ResponseEnum.WEIXIN_FETCH_USERINFO_ERROR);
        return userAccount.getAmount();
    }

    @Override
    public void updateBalanceAndFreezeMoney(BigDecimal voteAmt, Long userId) {
        baseMapper.updateBalanceAndFreezeMoney(voteAmt,userId);
    }
}
